package com.ruoyi.receipt.utils;

import com.ruoyi.common.constant.RedisConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.IdWorker;
import com.ruoyi.receipt.domain.TbRecordOnlineUser;
import com.ruoyi.receipt.domain.TbStatisAnalysis;
import com.ruoyi.receipt.domain.TbUser;
import com.ruoyi.receipt.service.ITbRecordOnlineUserService;
import com.ruoyi.receipt.service.ITbStatisAnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/alarmTask")
@Component("alarmTask")
public class AlarmTask {

    @Autowired
    private ITbRecordOnlineUserService onlineUserService;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RedisCache redisCache;

    @Autowired
    StatisAnalysisUtils statisAnalysisUtils;

    @Autowired
    FormulaUtil formulaUtil;

    @Autowired
    ITbStatisAnalysisService tbStatisAnalysisService;

    @Autowired
    IdWorker idWorker;

    //@Scheduled(cron = "0 */1 * * * *")
    @PostMapping("/scheduled")
    public void run() throws InterruptedException {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//显示2021-04-06格式
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = null;
        try {
            parse = formatter.parse(simpleDateFormat.format(date) + " 08:00:00");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //获取当前时间 如果当前时间是0点到8点统计昨天的综合分 如果是其他时间段统计今天的数据
        //判断当前时间是否大于八点 大于8点统计今天的综合分
        if (date.compareTo(parse) > 0){
            int i = onlineUserService.insertOnlineUserTody();
            String formatDate = simpleDateFormat.format(date);
            //1.通过tb_user表查询所有昨天登录的用户并将这些用户插入到tb_record_online_user表中
            if (i > 0){
                //2.从tb_record_online_user表中查询所有的已经插入的昨天登录的用户信息
                List<TbRecordOnlineUser> oldTbRecordOnlineUsers = onlineUserService.selectTodayOnlineUser();
                List<TbRecordOnlineUser> tbRecordOnlineUsers = oldTbRecordOnlineUsers.stream().filter(item -> item.getType() == 2).collect(Collectors.toList());
                //3.循环遍历查到的用户信息后根据用户手机号去redis中获取考试信息
                if (tbRecordOnlineUsers.size() > 0){
                    for (int i1 = 0; i1 < tbRecordOnlineUsers.size(); i1++) {
                        String loginAccount = tbRecordOnlineUsers.get(i1).getUserId().toString();//获取该用户的登录手机号
                        //向tb_statis_analysis统计分析表中存放一条记录
                        //1.统计今日总做题数
                        Long todyCount = redisTemplate.opsForZSet().size(RedisConstants.TODAY_ALL_SUBJECT + formatDate+":"+loginAccount);
                        //2.统计今日错题数
                        Long todyWrongCount = redisTemplate.opsForZSet().size(RedisConstants.TODAY_WRONG_SUBJECT + formatDate+":"+loginAccount);
                        //3.统计今日切出次数
                        Double todyCutOutTimes = redisTemplate.opsForZSet().score(RedisConstants.TODAY_CUT_OUT_NUMBER+formatDate, Long.parseLong(loginAccount));
                        if (todyCutOutTimes == null){
                            todyCutOutTimes = 0.0;
                        }
                        //4.统计今日切出时长
                        Double cutOutTime = redisTemplate.opsForZSet().score(RedisConstants.TODAY_CUT_OUT_TIME+formatDate, Long.parseLong(loginAccount));
                        if (cutOutTime == null){
                            cutOutTime = 0.0;
                        }
                        //5.统计今日正确率(存放int类型整数 前端回显拼上百分号)
                        Double round = Double.valueOf(0);
                        //判断该用户今日有没有做过题
                        if (todyCount.intValue() > 0){
                            round = Math.floor(((todyCount.doubleValue() - todyWrongCount.doubleValue()) / todyCount.doubleValue()) * 100);
                        }
                        //6.统计今日学习时长
                        Double learnTime = redisTemplate.opsForZSet().score(RedisConstants.TODAY_LEARN_TIME+formatDate, Long.parseLong(loginAccount));
                        if (learnTime == null){
                            learnTime = 0.0;
                        }
                        //7.统计今日难度正确率
                        Long difGre35AllNum1 = statisAnalysisUtils.getDifGre35AllNum(Long.parseLong(loginAccount), formatDate);//用户做过的难度大于35的所有题目个数
                        Long difGre35RightNum = statisAnalysisUtils.getDifGre35RightNum(Long.parseLong(loginAccount), formatDate);//用户做过的难度大于35的正确题目个数
                        Double accuracyOfDifficulty = Double.valueOf(0);
                        //判断用户有没有做过难度大于35的题
                        if (difGre35AllNum1.intValue() > 0){
                            accuracyOfDifficulty = Math.floor((difGre35RightNum.doubleValue() / difGre35AllNum1.doubleValue()) * 100);
                        }
                        //8.统计今日时间分 入参传入今日学习时长 单位分钟 这里进行四舍五入
                        int timeScore = formulaUtil.time(learnTime.intValue());
                        //9.统计能力分 入参传入正确率
                        int capacityScore = formulaUtil.capacity(round.intValue());
                        //10.统计创新分 入参传入难题正确率
                        int innovateScore = formulaUtil.innovate(accuracyOfDifficulty.intValue());
                        //11.统计专注分 入参是切出次数和切出分钟
                        int focusScore = formulaUtil.fengrossment(todyCutOutTimes.intValue(), cutOutTime.intValue());
                        //12.统计综合分 入参学习时长 正确率 难题正确率 切出次数 切出分钟
                        int synthesizeScore = formulaUtil.synthesize(learnTime.intValue(), round.intValue(), accuracyOfDifficulty.intValue(), todyCutOutTimes.intValue(), cutOutTime.intValue());

                        //向tb_statis_analysis表中添加一条分析记录
                        TbStatisAnalysis tbStatisAnalysis = new TbStatisAnalysis();
                        //向实体类中放入用户信息
                        tbStatisAnalysis.setId(idWorker.nextId());
                        tbStatisAnalysis.setUserId(tbRecordOnlineUsers.get(i1).getUserId());
                        tbStatisAnalysis.setLoginAccount(tbRecordOnlineUsers.get(i1).getLoginAccount());
                        tbStatisAnalysis.setRealName(tbRecordOnlineUsers.get(i1).getRealName());
                        //向实体类中放入题数时长次数正确率等信息
                        tbStatisAnalysis.setTodayAllSubject(todyCount);
                        tbStatisAnalysis.setTodayWrongSubject(todyWrongCount);
                        tbStatisAnalysis.setTodayCutOutNumber(todyCutOutTimes.longValue());
                        tbStatisAnalysis.setTodayCutOutTime(cutOutTime.longValue());
                        tbStatisAnalysis.setTodayAccuracy(accuracyOfDifficulty.longValue());
                        tbStatisAnalysis.setTodayLearnTime(learnTime.longValue());
                        //向实体类中放入分值
                        tbStatisAnalysis.setTimeScore(Long.valueOf(timeScore));
                        tbStatisAnalysis.setCapacityScore(Long.valueOf(capacityScore));
                        tbStatisAnalysis.setInnovateScore(Long.valueOf(innovateScore));
                        tbStatisAnalysis.setFengrossmentScore(Long.valueOf(focusScore));
                        tbStatisAnalysis.setSynthesizeScore(Long.valueOf(synthesizeScore));
                        //向实体类中放入其他信息
                        tbStatisAnalysis.setIsDel(0);
                        tbStatisAnalysis.setLastLoginTime(tbRecordOnlineUsers.get(i1).getLastLoginTime());
                        tbStatisAnalysisService.insertTbStatisAnalysis(tbStatisAnalysis);
                    }
                }
            }
        //0点到8点统计昨天的综合分
        }else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            date = calendar.getTime();
            String formatDate = simpleDateFormat.format(date);
            //1.通过tb_user表查询所有昨天登录的用户并将这些用户插入到tb_record_online_user表中
            int i = onlineUserService.insertOnlineUserYestody();
            if (i > 0){
                //2.从tb_record_online_user表中查询所有的已经插入的昨天登录的用户信息
                List<TbRecordOnlineUser> oldTbRecordOnlineUsers = onlineUserService.selectYesterdayOnlineUser();
                List<TbRecordOnlineUser> tbRecordOnlineUsers = oldTbRecordOnlineUsers.stream().filter(item -> item.getType() == 2).collect(Collectors.toList());
                //3.循环遍历查到的用户信息后根据用户手机号去redis中获取考试信息
                if (tbRecordOnlineUsers.size() > 0){
                    for (int i1 = 0; i1 < tbRecordOnlineUsers.size(); i1++) {
                        String loginAccount = tbRecordOnlineUsers.get(i1).getUserId().toString();//获取该用户的登录手机号
                        //向tb_statis_analysis统计分析表中存放一条记录
                        //1.统计今日总做题数
                        Long todyCount = redisTemplate.opsForZSet().size(RedisConstants.TODAY_ALL_SUBJECT + formatDate+":"+loginAccount);
                        //2.统计今日错题数
                        Long todyWrongCount = redisTemplate.opsForZSet().size(RedisConstants.TODAY_WRONG_SUBJECT + formatDate+":"+loginAccount);
                        //3.统计今日切出次数
                        Double todyCutOutTimes = redisTemplate.opsForZSet().score(RedisConstants.TODAY_CUT_OUT_NUMBER+formatDate, Long.parseLong(loginAccount));
                        if (todyCutOutTimes == null){
                            todyCutOutTimes = 0.0;
                        }
                        //4.统计今日切出时长
                        Double cutOutTime = redisTemplate.opsForZSet().score(RedisConstants.TODAY_CUT_OUT_TIME+formatDate, Long.parseLong(loginAccount));
                        if (cutOutTime == null){
                            cutOutTime = 0.0;
                        }
                        //5.统计今日正确率(存放int类型整数 前端回显拼上百分号)
                        Double round = Double.valueOf(0);
                        //判断该用户今日有没有做过题
                        if (todyCount.intValue() > 0){
                            round = Math.floor(((todyCount.doubleValue() - todyWrongCount.doubleValue()) / todyCount.doubleValue()) * 100);
                        }
                        //6.统计今日学习时长
                        Double learnTime = redisTemplate.opsForZSet().score(RedisConstants.TODAY_LEARN_TIME+formatDate, Long.parseLong(loginAccount));
                        if (learnTime == null){
                            learnTime = 0.0;
                        }
                        //7.统计今日难度正确率
                        Long difGre35AllNum1 = statisAnalysisUtils.getDifGre35AllNum(Long.parseLong(loginAccount), formatDate);//用户做过的难度大于35的所有题目个数
                        Long difGre35RightNum = statisAnalysisUtils.getDifGre35RightNum(Long.parseLong(loginAccount), formatDate);//用户做过的难度大于35的正确题目个数
                        Double accuracyOfDifficulty = Double.valueOf(0);
                        //判断用户有没有做过难度大于35的题
                        if (difGre35AllNum1.intValue() > 0){
                            accuracyOfDifficulty = Math.floor((difGre35RightNum.doubleValue() / difGre35AllNum1.doubleValue()) * 100);
                        }
                        //8.统计今日时间分 入参传入今日学习时长 单位分钟 这里进行四舍五入
                        int timeScore = formulaUtil.time(learnTime.intValue());
                        //9.统计能力分 入参传入正确率
                        int capacityScore = formulaUtil.capacity(round.intValue());
                        //10.统计创新分 入参传入难题正确率
                        int innovateScore = formulaUtil.innovate(accuracyOfDifficulty.intValue());
                        //11.统计专注分 入参是切出次数和切出分钟
                        int focusScore = formulaUtil.fengrossment(todyCutOutTimes.intValue(), cutOutTime.intValue());
                        //12.统计综合分 入参学习时长 正确率 难题正确率 切出次数 切出分钟
                        int synthesizeScore = formulaUtil.synthesize(learnTime.intValue(), round.intValue(), accuracyOfDifficulty.intValue(), todyCutOutTimes.intValue(), cutOutTime.intValue());

                        //向tb_statis_analysis表中添加一条分析记录
                        TbStatisAnalysis tbStatisAnalysis = new TbStatisAnalysis();
                        //向实体类中放入用户信息
                        tbStatisAnalysis.setId(idWorker.nextId());
                        tbStatisAnalysis.setUserId(tbRecordOnlineUsers.get(i1).getUserId());
                        tbStatisAnalysis.setLoginAccount(tbRecordOnlineUsers.get(i1).getLoginAccount());
                        tbStatisAnalysis.setRealName(tbRecordOnlineUsers.get(i1).getRealName());
                        //向实体类中放入题数时长次数正确率等信息
                        tbStatisAnalysis.setTodayAllSubject(todyCount);
                        tbStatisAnalysis.setTodayWrongSubject(todyWrongCount);
                        tbStatisAnalysis.setTodayCutOutNumber(todyCutOutTimes.longValue());
                        tbStatisAnalysis.setTodayCutOutTime(cutOutTime.longValue());
                        tbStatisAnalysis.setTodayAccuracy(accuracyOfDifficulty.longValue());
                        tbStatisAnalysis.setTodayLearnTime(learnTime.longValue());
                        //向实体类中放入分值
                        tbStatisAnalysis.setTimeScore(Long.valueOf(timeScore));
                        tbStatisAnalysis.setCapacityScore(Long.valueOf(capacityScore));
                        tbStatisAnalysis.setInnovateScore(Long.valueOf(innovateScore));
                        tbStatisAnalysis.setFengrossmentScore(Long.valueOf(focusScore));
                        tbStatisAnalysis.setSynthesizeScore(Long.valueOf(synthesizeScore));
                        //向实体类中放入其他信息
                        tbStatisAnalysis.setIsDel(0);
                        tbStatisAnalysis.setLastLoginTime(tbRecordOnlineUsers.get(i1).getLastLoginTime());
                        tbStatisAnalysisService.insertTbStatisAnalysis(tbStatisAnalysis);
                    }
                }
            }
        }



    }

    //批量插入方法 用于统计分析
    @PostMapping("/bathZsetByList")
    public void bathZsetByList(@RequestBody Map<String,Object> map){
        String key = (String) map.get("key");
        String score = (String) map.get("score");
        double doubleScore = Double.parseDouble(score);
        List<Long> list = new ArrayList<>();
        for (int i = 80; i < 87; i++) {
            list.add(Long.valueOf(i));
        }
        redisCache.bathZsetByList(key,list,doubleScore);
    }

    //单条插入记录
    @PostMapping("/zSetAdd")
    public void zSetAdd(@RequestBody Map<String,Object> map){
        String key = (String) map.get("key");
        String zkey = (String) map.get("zkey");
        long zkeyLong = Long.parseLong(zkey);
        String score = (String) map.get("score");
        double doubleScore = Double.parseDouble(score);
       redisCache.zSetAdd(key,zkeyLong,doubleScore);
    }

    //推入今日切出次数/切出时长/今日学习时长
    @PostMapping("/putTodayCutOutNumTimes")
    public void putTodayCutOutNumber(@RequestBody Map<String,Object> map){
        String userId = (String) map.get("userId");
        long userIdLong = Long.parseLong(userId);
        String time = (String) map.get("time");
        int timeInt = Integer.parseInt(time);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//显示2021-04-06格式
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        date = calendar.getTime();
        String formatDate = simpleDateFormat.format(date);
        //推入切出次数
        //statisAnalysisUtils.putTodayCutOutNumber(userIdLong);
        redisCache.zSetIncrScore(RedisConstants.TODAY_CUT_OUT_NUMBER+formatDate,userIdLong,new Integer(1).doubleValue());
        //推入切出时长
        redisCache.zSetIncrScore(RedisConstants.TODAY_CUT_OUT_TIME+formatDate,userIdLong,Double.parseDouble(time));
        //statisAnalysisUtils.putTodayCutOutTime(userIdLong,timeInt);
        //推入学习时长
        redisCache.zSetIncrScore(RedisConstants.TODAY_LEARN_TIME+formatDate,userIdLong,Double.parseDouble(time));
        //statisAnalysisUtils.putTodayLearnTime(userIdLong,timeInt);
    }

    //推入用户做过的难度大于35的题目
    @PostMapping("/putDiffictRatioGreater35")
    public void putDiffictRatioGreater35(@RequestBody Map<String,Object> map){
        String subjectId = (String) map.get("subjectId");
        long subjectIdLong = Long.parseLong(subjectId);
        statisAnalysisUtils.putDiffictRatioGreater35(subjectIdLong);
    }

    //推入用户做过的难度大于35的题目
    @RequestMapping("/testMethod")
    public String testMethod(){
        return "这是什么鬼";
    }

}
